package appClientModule;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.smartcardio.ATR;
import javax.smartcardio.Card;
import javax.smartcardio.CardChannel;
import javax.smartcardio.CardException;
import javax.smartcardio.CardTerminal;
import javax.smartcardio.CardTerminals;
import javax.smartcardio.CommandAPDU;
import javax.smartcardio.ResponseAPDU;
import javax.smartcardio.TerminalFactory;
import javax.swing.JApplet;
import javax.swing.SwingUtilities;

import netscape.javascript.JSException;
import netscape.javascript.JSObject;

public class applet_pcsc extends JApplet {
	private static final long serialVersionUID = 1L;
	CardTerminal WorkingReader;
	public Card card;
	boolean CardIsPresent;
	String CardATR;
	int NbReaders;
	String ApduRsp;
	String ReaderName;
	String ConnectResponse = "";
	private JSObject jso;
	Thread cardPresentThread = null;
	CardInReader cir;
	public boolean flog;
	String[] rs = null;
	String cs = null;
	Notify CardPresentNotify = new Notify() {
		public void doneIt() {
			SwingUtilities.invokeLater(new Runnable() {
				public void run() {
					applet_pcsc.this.CardPresent();
				}
			});
		}
	};

	Thread cardAbsentThread = null;
	CardRemoved cr;
	Notify CardAbsentNotify = new Notify() {
		public void doneIt() {
			SwingUtilities.invokeLater(new Runnable() {
				public void run() {
					applet_pcsc.this.CardAbsent();
				}
			});
		}
	};

	public void stop() {
		KillThread();
	}

	public void init() {
		setSize(300, 80);
		try {
			this.jso = JSObject.getWindow(this);
		} catch (JSException e) {
			e.printStackTrace();
		}
	}

	public static void main(String args[]) {
		final applet_pcsc ap = new applet_pcsc();
		final String readername = "OMNIKEY Smart Card Reader USB 0";// "ACS ACR1281 1S Dual Reader ICC 0";
		try {

			TerminalFactory factory = TerminalFactory.getDefault();
			CardTerminals terminalList = factory.terminals();
			ap.WorkingReader = terminalList.getTerminal(readername);
			String OS = System.getProperty("os.name");
			if (OS.startsWith("Windows")) {
				try {
					if (ap.WorkingReader.isCardPresent()) {
						ap.cr = new CardRemoved(ap.WorkingReader);
						ap.cr.addNotifyListener(ap.CardAbsentNotify);
						ap.cardAbsentThread = new Thread(ap.cr);
						ap.cardAbsentThread.start();
					} else
						ap.CardAbsent();
				} catch (CardException e1) {
					e1.printStackTrace();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println(readername);
		// ap.IsCardPresent();
		ap.Connect("*");
		// »ñÈ¡¿¨ÐÅÏ¢²âÊÔ
		// System.out.println(getCardInfoTest.getCardInfoTest(ap));
		// °²×°²âÊÔ
		// ap.Connect("*");
		// CapInstallTest.test(ap);
		String request = "";// "05000389030366001E428DA761E4D30B8844FEEAD6C6CB5B518E0A310E8B99DB476F8A84906DF9A0C5CC41F188B1D225930B2D45B2A2";
		System.out.println(ap.activeApplet(request));

	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public boolean IsCardPresent() {
		try {
			AccessController.doPrivileged(new PrivilegedExceptionAction() {
				public Boolean run() {
					try {
						applet_pcsc.this.CardIsPresent = applet_pcsc.this.WorkingReader.isCardPresent();
						String OS = System.getProperty("os.name");
						if (OS.startsWith("Windows")) {
							try {
								if (applet_pcsc.this.WorkingReader.isCardPresent())
									applet_pcsc.this.CardPresent();
								else
									applet_pcsc.this.CardAbsent();
							} catch (CardException e1) {
								e1.printStackTrace();
							}
						}
					} catch (CardException e) {
						e.printStackTrace();
					}
					return Boolean.valueOf(true);
				}
			});
		} catch (PrivilegedActionException e) {
			e.printStackTrace();
		}
		return this.CardIsPresent;
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public String SetReader(String newName) {
		final String NewReaderName = newName;
		try {
			AccessController.doPrivileged(new PrivilegedExceptionAction() {
				public Boolean run() {
					TerminalFactory factory = TerminalFactory.getDefault();
					CardTerminals terminalList = factory.terminals();
					applet_pcsc.this.WorkingReader = terminalList.getTerminal(NewReaderName);
					// String OS = System.getProperty("os.name");
					// if (OS.startsWith("Windows")) {
					// try {
					// if (applet_pcsc.this.WorkingReader.isCardPresent())
					// applet_pcsc.this.CardPresent();
					// else
					// applet_pcsc.this.CardAbsent();
					// } catch (CardException e1) {
					// e1.printStackTrace();
					// }
					// }
					return Boolean.valueOf(true);
				}
			});
		} catch (PrivilegedActionException e) {
			e.printStackTrace();
		}
		return this.WorkingReader.getName();
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public void Disconnect(boolean reset) {
		final boolean ResetChoice = reset;
		try {
			AccessController.doPrivileged(new PrivilegedExceptionAction() {
				public Boolean run() {
					try {
						applet_pcsc.this.card.disconnect(ResetChoice);
					} catch (CardException e) {
						e.printStackTrace();
					}
					return Boolean.valueOf(true);
				}
			});
		} catch (PrivilegedActionException e) {
			e.printStackTrace();
		}
	}

	public String cardReset() {
		try {
			Disconnect(true);
			return Connect("*");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	/**应用激活*/
	public String activeApplet(String request) {
		try {
			final String param = request;
			AccessController.doPrivileged(new PrivilegedExceptionAction() {
				public String sendApdu(String apdu) {
					System.out.println(">>" + apdu);
					String resp = applet_pcsc.this.TransmitString(apdu);
					System.out.println("<<" + resp);
					return resp;
				}
				//初始方法, 获取应用AID
				private boolean initMethod() {
					String ret = "";
					String aid = "";
					String resp = "";
					Map retMap = new HashMap();
					ObjectMapper mapper = new ObjectMapper();
					// ³õÊ¼·½·¨
					ret = sendApdu("00a40004022f00");
					byte[] retmsg = MsgGenUtil.BCD2Bytes(ret);
					// »ñÈ¡aid
					if (retmsg[3] == 0x05) {
						byte[] record = new byte[1];
						record[0] = retmsg[8];
						int index = Integer.parseInt(MsgGenUtil.buf2hex(record), 10);
						byte[] length = new byte[2];
						System.arraycopy(retmsg, 6, length, 0, 2);
						int len = Integer.parseInt(MsgGenUtil.buf2hex(length), 10);

						for (int i = 1; i <= index; i++) {
							ret = "";
							ret = sendApdu("00b2" + MsgGenUtil.buf2hex(MsgGenUtil.Int2Bytes1(i)) + "04" + len);
							retmsg = null;
							retmsg = MsgGenUtil.BCD2Bytes(ret);
							byte[] length2 = new byte[1];
							length2[0] = retmsg[3];
							int len2 = Integer.parseInt(MsgGenUtil.buf2hex(length2), 16);
							if (ret.contains("871002")) {
								aid = ret.substring(8, len2 * 2 + 8);
								break;
							}
						}
						ret = sendApdu("00a4040410" + aid);
						if (!ret.substring(ret.length() - 4).equals("9000")) {
							retMap.put("resultCode", 1);
							retMap.put("resultIndex", "");
							retMap.put("resultResponse", ret.substring(0, ret.length() - 4));
							retMap.put("resultSW", ret.substring(ret.length() - 4));
							try {
								resp = mapper.writeValueAsString(retMap);
							} catch (JsonProcessingException e) {
								e.printStackTrace();
								applet_pcsc.this.ApduRsp = "Ñ¡Ôñaid´íÎó";
								return false;
							}
							applet_pcsc.this.ApduRsp = resp;
							return false;
						}
					}
					return true;
				}

				@Override
				public String run() throws Exception {
					String resp = "";
					boolean flag = true;
					if (param.equals("") && param.length() == 0) {
						flag = initMethod();
						if (!flag) {
							return applet_pcsc.this.ApduRsp;
						}
						//上行短信处理
						resp = shangxing();
						applet_pcsc.this.ApduRsp = resp;
						return applet_pcsc.this.ApduRsp;
					} else {
						// 下行短信处理
						resp = xiaxing(param);						
						applet_pcsc.this.ApduRsp = resp;
						return applet_pcsc.this.ApduRsp;
					}
				}
				//下行方法处理
				@SuppressWarnings("static-access")
				private String xiaxing(String param) {
					DownloadMsg gt = null;
					ObjectMapper mapper = new ObjectMapper();
					String ret = "";
					String resp = "";
					try {
						gt = mapper.readValue(param, DownloadMsg.class);
					} catch (JsonParseException e) {
						e.printStackTrace();
					} catch (JsonMappingException e) {
						e.printStackTrace();
					} catch (IOException e) {
						e.printStackTrace();
					}
					String[] coms = gt.GetMTSMSResponse.getMTSMSContent();
					Map upMap = new HashMap();
					for (String com : coms) {
						ActiveApplet aa = new ActiveApplet();
						String downmsg = aa.downMsg(com);
						ret = sendApdu(downmsg);
						// 9000µÄ¼ÌÐøÖ´ÐÐÏÂÒ»ÌõÏÂÐÐ¶ÌÐÅ
						if (ret.substring(ret.length() - 4).equals("9000")) {
							continue;
						}
						if (ret.substring(ret.length() - 4).startsWith("91")) {
							resp = shangxing();
							return resp;
						} else {
							upMap.put("resultCode", 1);
							upMap.put("resultIndex", downmsg);
							upMap.put("resultResponse", ret.substring(0, ret.length() - 4));
							upMap.put("resultSW", ret.substring(ret.length() - 4));
						}
					}
					try {
						resp = mapper.writeValueAsString(upMap);
					} catch (JsonProcessingException e) {
						e.printStackTrace();
					}
					return resp;
				}
				//ÉÏÐÐ²Ù×÷
				private String shangxing() {
					Map retMap = new HashMap();
					ObjectMapper mapper = new ObjectMapper();
					String ret = "";
					String resp = "";
					try {
						// ·¢ËÍ8010Ö¸Áî
						ret = sendApdu("801000001EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000");
						if (ret.substring(ret.length() - 4).equals("9000")) {
							Map map = upMsg();
							resp = mapper.writeValueAsString(map);
							return resp;
						} else if (ret.substring(ret.length() - 4).startsWith("91")) {
							Map map = m8012(ret);
							resp = mapper.writeValueAsString(map);
							return resp;
						} else {
							retMap.put("resultCode", 1);
							retMap.put("resultIndex", "");
							retMap.put("resultResponse", ret.substring(0, ret.length() - 4));
							retMap.put("resultSW", ret.substring(ret.length() - 4));
							resp = mapper.writeValueAsString(retMap);
							return resp;
						}
					} catch (JsonProcessingException e) {
						e.printStackTrace();
					}
					return null;
				}
				/**完整的上行运行*/
				private Map upMsg() {
					// ÉÏÐÐ
					Map map = new HashMap();
					int count = 1;
					String ret = eight("80F2000000", count);
					if (!ret.substring(ret.length() - 4).startsWith("91")) {
						map.put("resultCode", 1);
						map.put("resultIndex", "80F2000000");
						map.put("resultResponse", ret.substring(0, ret.length() - 4));
						map.put("resultSW", ret.substring(ret.length() - 4));
						return map;
					}
					map = m8012(ret);
					return map;
				}

				@SuppressWarnings("static-access")
				//8012命令处理
				private Map m8012(String ret) {
					Map map = new HashMap();
					ret = sendApdu("80120000" + ret.substring(ret.length() - 2));
					if (ret.substring(ret.length() - 4).equals("9000")) {
						ActiveApplet aa = new ActiveApplet();
						String resp = aa.activeAppletCap(ret.substring(4, ret.length() - 4));
						if (resp.equals("")) {
							map = m8014(ret);
						} else {
							map = m8014(ret);
							map.put("resultCode", 0);
							map.put("resultIndex", "");
							map.put("resultResponse", resp);
							map.put("resultSW", "");
						}
					} else {
						map.put("resultCode", 1);
						map.put("resultIndex", "");
						map.put("resultResponse", ret.substring(0, ret.length() - 4));
						map.put("resultSW", ret.substring(ret.length() - 4));
					}
					return map;
				}
				//8014命令处理
				private Map m8014(String ret) {
					Map map = new HashMap();
					if (ret.substring(ret.length() - 4).equals("9000")) {
						if (ret.substring(8, 14).equals("010500")) {
							ret = sendApdu("801400000C810301050002028281030100");
							if (ret.substring(ret.length() - 4).equals("9000")) {
								map = upMsg();
							} else if (ret.substring(ret.length() - 4).startsWith("91")) {
								map = m8012(ret);
							} else {
								map.put("resultCode", 1);
								map.put("resultIndex", "801400000C810301050002028281030100");
								map.put("resultResponse", ret.substring(0, ret.length() - 4));
								map.put("resultSW", ret.substring(ret.length() - 4));
								return map;
							}
						} else if (ret.substring(8, 14).equals("012500")) {
							ret = sendApdu("801400000C810301250002028281830100");
							if (ret.substring(ret.length() - 4).equals("9000")) {
								map = upMsg();
							} else if (ret.substring(ret.length() - 4).startsWith("91")) {
								map = m8012(ret);
							} else {
								map.put("resultCode", 1);
								map.put("resultIndex", "801400000C810301250002028281830100");
								map.put("resultResponse", ret.substring(0, ret.length() - 4));
								map.put("resultSW", ret.substring(ret.length() - 4));
								return map;
							}
						} else if (ret.substring(8, 14).equals("010400")) {
							ret = sendApdu("801400000C810301040002028281030100");
							if (ret.substring(ret.length() - 4).equals("9000")) {
								map = upMsg();
							} else if (ret.substring(ret.length() - 4).startsWith("91")) {
								map = m8012(ret);
							} else {
								map.put("resultCode", 1);
								map.put("resultIndex", "801400000C810301040002028281030100");
								map.put("resultResponse", ret.substring(0, ret.length() - 4));
								map.put("resultSW", ret.substring(ret.length() - 4));
								return map;
							}
						} else if (ret.substring(8, 14).equals("010300")) {
							ret = sendApdu("80140000108103010300020282810301000402011E");
							if (ret.substring(ret.length() - 4).equals("9000")) {
								map = upMsg();
							} else if (ret.substring(ret.length() - 4).startsWith("91")) {
								map = m8012(ret);
							} else {
								map.put("resultCode", 1);
								map.put("resultIndex", "80140000108103010300020282810301000402011E");
								map.put("resultResponse", ret.substring(0, ret.length() - 4));
								map.put("resultSW", ret.substring(ret.length() - 4));
								return map;
							}
						} else if (ret.substring(8, 14).equals("014001")) {
							ret = sendApdu("801400000C810301400102028281030100");
							if (ret.substring(ret.length() - 4).equals("9000")) {
								map = upMsg();
							} else if (ret.substring(ret.length() - 4).startsWith("91")) {
								map = m8012(ret);
							} else {
								map.put("resultCode", 1);
								map.put("resultIndex", "801400000C" + ret.substring(4, ret.length() - 4));
								map.put("resultResponse", ret.substring(0, ret.length() - 4));
								map.put("resultSW", ret.substring(ret.length() - 4));
								return map;
							}
						} else if (ret.substring(8, 14).equals("011300")) {
							ret = sendApdu("801400000C810301130002028281030100");
							if (ret.substring(ret.length() - 4).equals("9000")) {
								return map;
							}
						}
					} else {
						map.put("resultCode", 1);
						map.put("resultIndex", "80120000" + ret.substring(ret.length() - 2));
						map.put("resultResponse", ret.substring(0, ret.length() - 4));
						map.put("resultSW", ret.substring(ret.length() - 4));
						return map;
					}
					return map;
				}
				//循环80f2指令，count指定运行多少次，如果结果不正确则退出
				private String eight(String command, int count) {
					String ret = sendApdu(command);
					if (ret.substring(ret.length() - 4).equals("9000")) {
						count++;
						if (count == 20) {
							return ret;
						}
						ret = eight(command, count);
					}
					return ret;
				}
			});
		} catch (PrivilegedActionException e) {
			e.printStackTrace();
		}
		return applet_pcsc.this.ApduRsp;
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	/**安装cap包接口*/
	public String installAppletCap(String install) {
		try {
			final String installs = install;
			AccessController.doPrivileged(new PrivilegedExceptionAction() {

				//安装，判断指令返回结果是否与预定值相同，不同则退出
				public Map<String, String> install(String request) {
					RequestInfo req = null;
					String resp = "";
					Map retMap = new HashMap();
					System.out.println("ÇëÇóÊý¾Ý" + request);

					/*
					 * System.out.println(">>00a40004023f00"); resp =
					 * applet_pcsc.this.TransmitString("00a40004023f00");
					 * System.out.println("<<"+resp);
					 */

					ObjectMapper mapper = new ObjectMapper();
					try {
						req = mapper.readValue(request, RequestInfo.class);
						if (req != null) {
							List<Apdu> apduList = req.getCAPDUList();
							int apduIndex = 1;
							for (int i = 0; i < apduList.size(); i++) {
								Apdu apdu = apduList.get(i);
								if (Integer.parseInt(apdu.getIndex()) == apduIndex) {
									System.out.println(">>" + apdu.getAPDU());
									resp = applet_pcsc.this.TransmitString(apdu.getAPDU());
									System.out.println("<<" + resp);
									boolean flag = false;
									for (String ru : apdu.getSW()) {
										if (resp.substring(resp.length() - 4).equals(ru)) {
											flag = true;
											break;
										} else {
											continue;
										}
									}
									if (!flag) {
										retMap.put("resultCode", 1);
										retMap.put("resultIndex", "" + apduIndex);
										retMap.put("resultResponse", resp.substring(0, resp.length() - 4));
										retMap.put("resultSW", resp.substring(resp.length() - 4));
										return retMap;
									}
									if (i != apduList.size() - 1) {
										apduIndex++;
									}
								}
							}
							retMap.put("resultCode", 0);
							retMap.put("resultIndex", "" + apduIndex);
							retMap.put("resultResponse", resp.substring(0, resp.length() - 4));
							retMap.put("resultSW", resp.substring(resp.length() - 4));
						}
					} catch (IOException e) {
						e.printStackTrace();
					}
					return retMap;
				}

				public String run() {
					// ÏÈ²åÈë¿¨Æ¬
					// IsCardPresent();
					// ÏìÓ¦½á¹û
					// Connect("*");

					ObjectMapper mapper = new ObjectMapper();
					Map retMap = new HashMap();

					//开始安装
					retMap = install(installs);
					String resp = "";
					try {
						resp = mapper.writeValueAsString(retMap);
					} catch (JsonProcessingException e) {
						System.out.println("CAP°²×°Ê§°Ü");
						e.printStackTrace();
					}
					applet_pcsc.this.ApduRsp = resp;
					return applet_pcsc.this.ApduRsp;
				}
			});
		} catch (PrivilegedActionException e) {
			e.printStackTrace();
		}
		return applet_pcsc.this.ApduRsp;
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	/**获取卡片信息*/
	public String getCardInfo() {
		try {
			AccessController.doPrivileged(new PrivilegedExceptionAction() {
				@SuppressWarnings("static-access")
				//与卡交互
				public byte[] sendApdu(String apdu) {
					System.out.println(">>" + apdu);
					String resp = applet_pcsc.this.TransmitString(apdu);
					System.out.println("<<" + resp);
					return applet_pcsc.this.hexStringToByteArray(resp);
				}
				//字节转换
				public byte[] byteConvert(byte[] src) {
					byte[] response = new byte[src.length];
					for (int i = 0; i < response.length; i++) {
						response[i] = src[response.length - 1 - i];
					}
					return response;
				}
				//转换imsi信息
				public String f22ToImsi(String ret) {
					String MIN_A = ret.substring(2, 6);
					String MIN_B = ret.substring(6, 12);
					String CC = ret.substring(12, 14);
					String DDDD = ret.substring(16, ret.length());
					StringBuffer sb = new StringBuffer();
					byte[] min_a = MsgGenUtil.BCD2Bytes(MIN_A);
					min_a = byteConvert(min_a);
					String min_value = "" + (MsgGenUtil.makeInt(min_a) + 111);
					String min = rValue3(min_value);

					byte[] min_b = MsgGenUtil.BCD2Bytes(MIN_B);
					min_b = byteConvert(min_b);
					int d = MsgGenUtil.makeInt(min_b);
					String BBBBBB = Integer.toBinaryString(d);

					String ett = BBBBBB.substring(BBBBBB.length() - 10, BBBBBB.length());// 8~10
					min_value = "" + (Integer.valueOf(ett, 2) + 111);
					ett = rValue3(min_value);

					String serven = BBBBBB.substring(BBBBBB.length() - 10 - 4, BBBBBB.length() - 10);// 8~10
					serven = "" + (Integer.valueOf(serven, 2));
					serven = rValue1(serven);

					String four = BBBBBB.substring(0, BBBBBB.length() - 10 - 4);// 8~10
					four = "" + (Integer.valueOf(four, 2) + 111);
					four = rValue3(four);

					byte[] min_c = MsgGenUtil.BCD2Bytes(CC);
					String mnc = "" + (min_c[0] + 11);
					mnc = rValue2(mnc);

					byte[] min_d = MsgGenUtil.BCD2Bytes(DDDD);
					min_d = byteConvert(min_d);
					String mcc = "" + (MsgGenUtil.makeInt(min_d) + 111);
					mcc = rValue3(mcc);

					sb.append(mcc);
					sb.append(mnc);
					sb.append(min);
					sb.append(four);
					sb.append(serven);
					sb.append(ett);

					System.out.println(sb.toString());
					return sb.toString();
				}
				//2位数值处理
				public String rValue2(String v) {
					String min_value = v;
					int two = Integer.parseInt(min_value.substring(min_value.length() - 1, min_value.length()));
					if (two == 0)
						min_value = "" + (Integer.parseInt(min_value) - 10);

					int one = Integer.parseInt(min_value.substring(0, min_value.length() - 1));
					if (one == 0 || one == 10)
						min_value = "" + (Integer.parseInt(min_value) - 10 * 10);
					// System.out.println(min_value);
					for (int i = min_value.length(); i < 2; i++) {
						min_value = "0" + min_value;
					}
					return min_value;
				}
				//3位数值处理
				public String rValue3(String v) {
					String min_value = v;

					int three = Integer.parseInt(min_value.substring(min_value.length() - 1, min_value.length()));
					if (three == 0)
						min_value = "" + (Integer.parseInt(min_value) - 10);

					int two = Integer.parseInt(min_value.substring(min_value.length() - 2, min_value.length() - 1));
					if (two == 0)
						min_value = "" + (Integer.parseInt(min_value) - 10 * 10);
					int one = Integer.parseInt(min_value.substring(0, min_value.length() - 2));
					if (one == 0 || one == 10)
						min_value = "" + (Integer.parseInt(min_value) - 10 * 100);
					for (int i = min_value.length(); i < 3; i++) {
						min_value = "0" + min_value;
					}
					return min_value;
				}
				//1位数据处理
				public String rValue1(String v) {
					String min_value = v;
					int one = Integer.parseInt(min_value.substring(0, min_value.length()));
					if (one >= 10)
						min_value = "" + (Integer.parseInt(min_value) % 10);
					return min_value;
				}
				//开始运行
				public String run() {
					Map map = new HashMap();
					byte[] retmsg = null;
					String ret = "";
					// ÏÈ²åÈë¿¨Æ¬
					// IsCardPresent();
					// ÏìÓ¦½á¹û
					ret = Connect("*");

					if (ret != null && ret.length() != 0) {
						map.put("resultCode", 0);
						map.put("CStatus", "1");
					} else {
						map.put("resultCode", 1);
						map.put("CStatus", "0");
					}

					map.put("resultDesc", ret);
					// ÅÐ¶Ï°²×°cap°ü°æ±¾
					map.put("CAPVersion", "");
					// ÅÐ¶Ï¿¨ÄÚ¼¤»î×´Ì¬
					map.put("RStatus", "");
					// ÅÐ¶Ï¿¨Æ¬ÖÆÔìÉÌ
					map.put("CardFirm", "");
					// ÅÐ¶Ï¿¨Æ¬Ê£Óà¿Õ¼ä
					map.put("Space", "");
					// È¡¿¨Æ¬iccid
					String aid = "";

					retmsg = sendApdu("00a40004023f00");
					ret = MsgGenUtil.buf2hex(retmsg);

					retmsg = sendApdu("00a40004022fe2");
					ret = MsgGenUtil.buf2hex(retmsg);

					retmsg = sendApdu("00b000000a");
					ret = MsgGenUtil.buf2hex(retmsg);
					if (!ret.substring(ret.length() - 4, ret.length()).equals("9000")) {
						map.put("ICCID", "");
					} else {
						byte[] iccid = convertByHighToLow(retmsg, 10);
						map.put("ICCID", MsgGenUtil.buf2hex(iccid));
					}
					// È¡iccid½áÊø---------
					// È¡4g aid-----------
					retmsg = sendApdu("00a40004022f00");
					ret = MsgGenUtil.buf2hex(retmsg);

					if (retmsg[3] == 0x05) {
						byte[] record = new byte[1];
						record[0] = retmsg[8];
						int index = Integer.parseInt(MsgGenUtil.buf2hex(record), 10);
						byte[] length = new byte[2];
						System.arraycopy(retmsg, 6, length, 0, 2);
						int len = Integer.parseInt(MsgGenUtil.buf2hex(length), 10);

						for (int i = 1; i <= index; i++) {
							retmsg = sendApdu("00b2" + MsgGenUtil.buf2hex(MsgGenUtil.Int2Bytes1(i)) + "04" + len);
							ret = MsgGenUtil.buf2hex(retmsg);
							byte[] length2 = new byte[1];
							length2[0] = retmsg[3];
							int len2 = Integer.parseInt(MsgGenUtil.buf2hex(length2), 16);
							if (ret.contains("871002")) {
								aid = ret.substring(8, len2 * 2 + 8);
								break;
							}
						}
					}
					// »ñÈ¡4g aid½áÊø-----

					// È¡gsm imsi
					retmsg = sendApdu("00a40004027f20");
					ret = MsgGenUtil.buf2hex(retmsg);

					retmsg = sendApdu("00a40004026f07");
					ret = MsgGenUtil.buf2hex(retmsg);

					retmsg = sendApdu("00b0000009");
					ret = MsgGenUtil.buf2hex(retmsg);
					if (!ret.substring(ret.length() - 4, ret.length()).equals("9000")) {
						map.put("G-IMSI", "");
					} else {
						int l = retmsg[1] >> 4 & 0x0f;
						byte[] data = new byte[7];
						System.arraycopy(retmsg, 2, data, 0, data.length);
						byte[] imsi = convertByHighToLow(data, data.length);
						System.out.println(l + MsgGenUtil.buf2hex(imsi));
						map.put("G-IMSI", l + MsgGenUtil.buf2hex(imsi));
					}
					// ----------- 2g imsi---½áÊø
					// È¡cdma imsi
					retmsg = sendApdu("00a40004027f25");
					ret = MsgGenUtil.buf2hex(retmsg);
					retmsg = sendApdu("00a40004026f22");
					ret = MsgGenUtil.buf2hex(retmsg);
					retmsg = sendApdu("00b000000a");
					ret = MsgGenUtil.buf2hex(retmsg);
					if (!ret.substring(ret.length() - 4, ret.length()).equals("9000")) {
						map.put("C-IMSI", "");
					} else {
						String cdma = f22ToImsi(ret.substring(0, ret.length() - 4));
						map.put("C-IMSI", cdma);
					}
					// ----------- cdma imsi---½áÊø
					// È¡lte imsi
					retmsg = sendApdu("00a4040410" + aid);
					ret = MsgGenUtil.buf2hex(retmsg);

					retmsg = sendApdu("00a40004026f07");
					ret = MsgGenUtil.buf2hex(retmsg);

					retmsg = sendApdu("00b0000009");
					ret = MsgGenUtil.buf2hex(retmsg);
					if (!ret.substring(ret.length() - 4, ret.length()).equals("9000")) {
						map.put("L-IMSI", "");
					} else {
						int l = retmsg[1] >> 4 & 0x0f;
						byte[] data = new byte[7];
						System.arraycopy(retmsg, 2, data, 0, data.length);
						byte[] imsi = convertByHighToLow(data, data.length);
						System.out.println(l + MsgGenUtil.buf2hex(imsi));
						map.put("L-IMSI", l + MsgGenUtil.buf2hex(imsi));

					}
					// ----------- lte imsi---½áÊø
					// ÅÐ¶ÏÊÇ²»»ØÎªNFC¿¨Æ¬
					// ret = cardReset();
					// if (ret != "") {
					// return "¸´Î»Ê§°Ü";
					// }
					retmsg = sendApdu("00a4040407A0000001510000");
					ret = MsgGenUtil.buf2hex(retmsg);
					if (ret.substring(ret.length() - 4, ret.length()).equals("9000")) {
						map.put("CardType", "1");
					} else {
						map.put("CardType", "2");
					}

					ObjectMapper mapper = new ObjectMapper();
					String json = "";
					try {
						json = mapper.writeValueAsString(map);
					} catch (JsonProcessingException e) {
						e.printStackTrace();
					}
					applet_pcsc.this.ApduRsp = json;

					return applet_pcsc.this.ApduRsp;
				}
				//高低位互换
				private byte[] convertByHighToLow(byte[] retmsg, int length) {
					byte[] data = new byte[length];
					for (int i = 0; i < data.length; i++) {
						byte a = retmsg[i];
						int b1 = a << 4 & 0xf0;
						int b2 = a >> 4 & 0x0f;
						data[i] = (byte) (b1 + b2);
					}
					System.out.println(MsgGenUtil.buf2hex(data));
					return data;
				}
			});
		} catch (PrivilegedActionException e) {
			e.printStackTrace();
		} finally {
			Disconnect(false);
		}
		return applet_pcsc.this.ApduRsp;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public String TransmitString(String ApduIn) {
		final String ApduCmd = ApduIn;
		try {
			AccessController.doPrivileged(new PrivilegedExceptionAction() {
				public Boolean run() {
					CardChannel comm = applet_pcsc.this.card.getBasicChannel();
					CommandAPDU getData = new CommandAPDU(applet_pcsc.hexStringToByteArray(ApduCmd));
					try {
						ResponseAPDU resp = comm.transmit(getData);
						applet_pcsc.this.ApduRsp = applet_pcsc.byteArrayToHexString(resp.getBytes()).replace(" ", "");
					} catch (CardException e) {
						e.printStackTrace();
						applet_pcsc.this.ApduRsp = ("Exception " + e.getMessage());
					}

					return Boolean.valueOf(true);
				}
			});
		} catch (PrivilegedActionException e) {
			e.printStackTrace();
		}
		return this.ApduRsp;
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public String TransmitArray(byte[] ApduIn) {
		final byte[] ApduCmd = ApduIn;
		try {
			AccessController.doPrivileged(new PrivilegedExceptionAction() {
				public Boolean run() {
					CardChannel comm = applet_pcsc.this.card.getBasicChannel();
					CommandAPDU getData = new CommandAPDU(ApduCmd);
					try {
						ResponseAPDU resp = comm.transmit(getData);
						applet_pcsc.this.ApduRsp = applet_pcsc.byteArrayToHexString(resp.getBytes());
					} catch (CardException e) {
						e.printStackTrace();
						applet_pcsc.this.ApduRsp = ("Exception " + e.getMessage());
					}

					return Boolean.valueOf(true);
				}
			});
		} catch (PrivilegedActionException e) {
			e.printStackTrace();
		}
		return this.ApduRsp;
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public int GetReaderCount() {
		this.NbReaders = 0;
		try {
			AccessController.doPrivileged(new PrivilegedExceptionAction() {
				public Boolean run() {
					try {
						TerminalFactory factory = TerminalFactory.getDefault();
						CardTerminals terminalList = factory.terminals();
						applet_pcsc.this.NbReaders = terminalList.list().size();
					} catch (CardException e) {
						e.printStackTrace();
					}
					return Boolean.valueOf(true);
				}
			});
		} catch (PrivilegedActionException e) {
			e.printStackTrace();
		}
		return this.NbReaders;
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public String GetReaderName(int readerIndex) {
		final int Index = readerIndex;
		try {
			AccessController.doPrivileged(new PrivilegedExceptionAction() {
				public Boolean run() {
					try {
						TerminalFactory factory = TerminalFactory.getDefault();
						CardTerminals terminalList = factory.terminals();
						applet_pcsc.this.ReaderName = ((CardTerminal) terminalList.list().get(Index)).getName();
					} catch (CardException e) {
						e.printStackTrace();
					}
					return Boolean.valueOf(true);
				}
			});
		} catch (PrivilegedActionException e) {
			e.printStackTrace();
		}
		return this.ReaderName;
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public String GetATR() {
		try {
			AccessController.doPrivileged(new PrivilegedExceptionAction() {
				public Boolean run() {
					try {
						Card card = applet_pcsc.this.WorkingReader.connect("*");

						ATR atr = card.getATR();
						applet_pcsc.this.CardATR = applet_pcsc.byteArrayToHexString(atr.getBytes()).replaceAll(" ", "");
					} catch (CardException e) {
						e.printStackTrace();
					}
					return Boolean.valueOf(true);
				}
			});
		} catch (PrivilegedActionException e) {
			e.printStackTrace();
		}
		return this.CardATR;
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public String Connect(String protocol) {
		final String Protocol_str = protocol;
		try {
			AccessController.doPrivileged(new PrivilegedExceptionAction() {
				public Integer run() {
					try {
						applet_pcsc.this.CardIsPresent = applet_pcsc.this.WorkingReader.isCardPresent();
						String OS = System.getProperty("os.name");
						if (OS.startsWith("Windows")) {
							try {
								if (applet_pcsc.this.WorkingReader.isCardPresent())
									applet_pcsc.this.CardPresent();
								else
									applet_pcsc.this.CardAbsent();
							} catch (CardException e1) {
								e1.printStackTrace();
							}
						}
						applet_pcsc.this.card = applet_pcsc.this.WorkingReader.connect(Protocol_str);
						if (applet_pcsc.this.card != null) {
							String atr = applet_pcsc.byteArrayToHexString(applet_pcsc.this.card.getATR().getBytes())
									.replaceAll(" ", "");
							applet_pcsc.this.ConnectResponse = atr;
						}
					} catch (CardException e) {
						e.printStackTrace();
						try {
							if (applet_pcsc.this.WorkingReader.isCardPresent())
								applet_pcsc.this.ConnectResponse = "Cannot connect card, try with another protocol";
							else
								applet_pcsc.this.ConnectResponse = "Put a card in the reader before connecting";
						} catch (CardException e1) {
							e1.printStackTrace();
						}
					}
					return null;
				}
			});
		} catch (PrivilegedActionException e) {
			e.printStackTrace();
		}
		return this.ConnectResponse;
	}

	static String byteArrayToHexString(byte[] bArray) {
		StringBuffer buffer = new StringBuffer();

		byte[] arrayOfByte = bArray;
		int j = bArray.length;
		for (int i = 0; i < j; i++) {
			byte b = arrayOfByte[i];

			buffer.append(String.format(" %02X", new Object[] { Byte.valueOf(b) }));
		}

		return buffer.toString().toUpperCase();
	}

	public static byte[] hexStringToByteArray(String s) {
		s = s.replace(" ", "");
		int len = s.length();
		byte[] data = new byte[len / 2];
		for (int i = 0; i < len; i += 2) {
			data[(i / 2)] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));
		}
		return data;
	}

	public void KillThread() {
		if ((this.cardPresentThread != null) && (this.cardPresentThread.isAlive())) {
			this.cir.removeNotifyListener(this.CardPresentNotify);
			Thread moribund = this.cardPresentThread;
			this.cardPresentThread = null;
			moribund.interrupt();
		}
		if ((this.cardAbsentThread != null) && (this.cardAbsentThread.isAlive())) {
			this.cr.removeNotifyListener(this.CardAbsentNotify);
			Thread moribund = this.cardAbsentThread;
			this.cardAbsentThread = null;
			moribund.interrupt();
		}
	}

	public void CardPresent() {
		// this.jso.call("RefreshCardState", new String[0]);
		KillThread();
		try {
			this.cr = new CardRemoved(this.WorkingReader);
			this.cr.addNotifyListener(this.CardAbsentNotify);
			this.cardAbsentThread = new Thread(this.cr);
			this.cardAbsentThread.start();
		} catch (Exception e1) {
			e1.printStackTrace();
		}
	}

	public void CardAbsent() {
		// this.jso.call("RefreshCardState", new String[0]);
		KillThread();
		try {
			this.cir = new CardInReader(this.WorkingReader);
			this.cardPresentThread = new Thread(this.cir);
			this.cardPresentThread.start();
			this.cir.addNotifyListener(this.CardPresentNotify);
		} catch (Exception e1) {
			e1.printStackTrace();
		}
	}
}
